import utils from '../utils.js';
import httpAdapter from './http.js';
import xhrAdapter from './xhr.js';
import fetchAdapter from './fetch.js';
import AxiosError from "../core/AxiosError.js";

const knownAdapters = {
    http: httpAdapter,
    xhr: xhrAdapter,
    fetch: fetchAdapter
}

utils.forEach(knownAdapters, (fn, value) => {
    if (fn) {
        try {
            Object.defineProperty(fn, 'name', {value});
        } catch (e) {
            // eslint-disable-next-line no-empty
        }
        Object.defineProperty(fn, 'adapterName', {value});
    }
});

const renderReason = (reason) => `- ${reason}`;

const isResolvedHandle = (adapter) => utils.isFunction(adapter) || adapter === null || adapter === false;

export default {
    getAdapter: (adapters) => {
        adapters = utils.isArray(adapters) ? adapters : [adapters];

        const {length} = adapters;
        let nameOrAdapter;
        let adapter;

        const rejectedReasons = {};

        for (let i = 0; i < length; i++) {
            nameOrAdapter = adapters[i];
            let id;

            adapter = nameOrAdapter;

            if (!isResolvedHandle(nameOrAdapter)) {
                adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];

                if (adapter === undefined) {
                    throw new AxiosError(`Unknown adapter '${id}'`);
                }
            }

            if (adapter) {
                break;
            }

            rejectedReasons[id || '#' + i] = adapter;
        }

        if (!adapter) {

            const reasons = Object.entries(rejectedReasons)
                .map(([id, state]) => `adapter ${id} ` +
                    (state === false ? 'is not supported by the environment' : 'is not available in the build')
                );

            let s = length ?
                (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) :
                'as no adapter specified';

            throw new AxiosError(
                `There is no suitable adapter to dispatch the request ` + s,
                'ERR_NOT_SUPPORT'
            );
        }

        return adapter;
    },
    adapters: knownAdapters
}
